#ifndef _CONFIGFILE_H
#define _CONFIGFILE_H

class ConfigProcessor;

class ConfigFile
    {
  public:
    int line_number;
    int indent;
    ConfigProcessor *proc;

    // path should not end with a /, but I think // usually gets collapsed
    ConfigFile (const char *path, const char *file)
        : proc(0), fl(0), filepath_write(0)
        {
        filepath = path;
        filename = file;
        }
    ConfigFile (char *path, const char *file)
        : proc(0), fl(0), filepath_write(0)
        {
        filepath = strdup(path);
        filename = file;
        }
    ~ConfigFile ()
        {
        // not close_file(), that finalizes a write.
        // (fl should not be open here anyway unless something went wrong..)
        if ( fl ) fclose(fl);
        if ( filepath_write ) free(filepath_write);
        }

    bool add_processor(ConfigProcessor *new_proc, bool check_for_match=false);
    void delete_processors();

    bool open_for_read();
    bool open_for_write();
    void cancel_write();
    void close_file();  // closes a reading file, finishes a writing file

    bool is_open() { return fl != 0; }
    void restart() { rewind(fl); }

    void perform_read();
    void perform_write();

    void write(const char *key, int minimum_key_width,
               bool leftjust, const char *value, ...);
    void write_comment(const char *comment);
    void write_label();  // called automagically by write() when proc changes
    void write(const char *str);  // mostly just for write("\n");

  protected:
    FILE *fl;
    const char *filepath;
    const char *filename;
    char *filepath_write;
    // time_t? filetime;

    list<ConfigProcessor *> procs;
    ConfigProcessor *last_write_proc;

    bool pr_check_for_label(char *p);
    bool scan_for_label(const char *label);
    };

class ConfigProcessor
    {
    friend class ConfigFile;
  public:
    const char *label;
    ConfigFile *cfgfile;
    bool present;

    ConfigProcessor() : present(false), reading(false) {}

    bool reading;
    virtual void init_read () {}
    virtual void read_done () {}
    virtual void data_read(const char *key, char *value)=0;
    void read_error(const char *key, const char *value, const char *expected=0);

    virtual void write_data () {}
    };

#endif // _CONFIGFILE_H
